// COPY FILES
// Version 1.0
// Ben DreamVB
//
//Usage:
// fc c:\games\doom\ c:\backup\doomwads\ /CS:1024
//
//Copy files with differnt size and no messages displayed using /q flag
//Usage:
// fc c:\games\doom\ c:\backup\doomwads\ /CS:2048 /Q
//
#include <iostream>
#include <Windows.h>
using namespace std;
using std::cout;
using std::endl;

string LCase(string s){
	string s0 = s;
	int i = 0;
	while (i < s0.length()){
		s0[i] = tolower(s0[i]);
		i++;
	}
	return s0;
}

string FixPath(string src){
	if (src[src.length() - 1] != '\\'){
		return src + "\\";
	}
	return src;
}

bool MyFileCopy(string src, string dest, int chunksize){
	FILE *fin = NULL;
	FILE *fout = NULL;
	char *Buffer = NULL;
	size_t BytesRead = 0;
	rsize_t BytesWrite = 0;

	//Open source file.
	fin = fopen(src.c_str(), "rb");

	if (!fin){
		return false;
	}

	fout = fopen(dest.c_str(), "wb");

	if (!fout){
		fclose(fin);
		return false;
	}

	//Resize Buffer
	Buffer = new char[chunksize];
	//Do file copy.

	//Get first data
	BytesRead = fread(Buffer, sizeof(char), chunksize, fin);

	//While not end of file read
	while (!feof(fin)){
		//Write data
		BytesWrite = fwrite(Buffer, sizeof(char), BytesRead, fout);
		//Read in new data.
		BytesRead = fread(Buffer, sizeof(char), chunksize, fin);
	}
	//Write remaining data.
	BytesWrite = fwrite(Buffer, sizeof(char), BytesRead, fout);

	//Tidy up time.
	fclose(fout);
	fclose(fin);
	delete[]Buffer;

	return true;
}

int main(int argc, char *argv[]){
	//Backup files from one folder to the other.

	char DirName[_MAX_PATH];
	//Tools variables
	int pos = 0;
	int Copied = 0;
	int Skipped = 0;
	int cpychunksize = 1024;
	//Folder and files variables
	string sSrcFolder = "";
	string sDestFolder = "";
	string sDirTemp = "";
	string Temp = "";
	string DestFile = "";
	string SrcFile = "";
	string ScanSrcDir = "";
	//Program arguments
	int parms = 3;
	bool Qmode = false;
	string sSwitch = "";
	
	//Find file variables
	HANDLE f = 0;
	WIN32_FIND_DATAA wfd;

	if (argc < 3){
		cout << "Usage: <SourceDir><DestDir>" << endl;
		exit(1);
	}

	while (parms < argc){
		if (argv[parms][0] == '/'){
			sSwitch = LCase(argv[parms]);
			//Check for : in switch
			pos = sSwitch.find(':');
			if (pos != string::npos){

				//Check for chunksize for the file copy function.
				if (sSwitch.substr(1, pos - 1) == "cs"){
					cpychunksize = atoi(sSwitch.substr(pos + 1).c_str());
					if (cpychunksize == 0){
						cpychunksize = 1024;
					}
				}
				//End of chunk size code
			}
			else{
				//Process other prams

				//Quite mode. does not display messages.
				if (sSwitch == "/q"){
					Qmode = true;
				}
			}
		}
		parms++;
	}

	//system("pause");
	//return 0;
	
	//Get source folder
	strcpy(DirName, argv[1]);
	sSrcFolder = FixPath(DirName);
	//Get dest folder
	strcpy(DirName, argv[2]);
	sDestFolder =FixPath(DirName);
	//Get last folder name from source path.
	sSrcFolder = FixPath(sSrcFolder);

	if (sSrcFolder[sSrcFolder.length() - 1] == '\\'){
		sDirTemp = sSrcFolder.substr(0, sSrcFolder.length() - 1);
		//Find last slash
		pos = sDirTemp.find_last_of('\\');
		//Check for last backslash in path.
		if (pos != string::npos){
			//Erase the path and just keep last folder name.
			sDirTemp.erase(0, pos+1);
			//Build new dest path
			Temp = sDestFolder + sDirTemp + "\\";
			//Create dest folder.
			CreateDirectoryA(sDestFolder.c_str(), NULL);
			
			//Create dest folder.
			CreateDirectoryA(Temp.c_str(), NULL);

			//Create the dest folder.
			sDestFolder = Temp;
			//Copy all files from source folder to dest

			//Set ScanSrcDir to fetch all file types.
			ScanSrcDir = sSrcFolder + "*.*";

			if (!Qmode){
				//Output source and destination paths
				cout << "Source       : " << sSrcFolder.c_str() << endl;
				cout << "Destination  : " << sDestFolder.c_str() << endl << endl;
			}

			//Get the first file.
			f = FindFirstFileA(ScanSrcDir.c_str(), &wfd);

			//Check for inaild return.
			if (f == INVALID_HANDLE_VALUE){
				cout << "Error scanning...." << sSrcFolder.c_str() << endl;
				exit(1);
			}

			//Gets the files.
			while (FindNextFileA(f, &wfd) != false){
				if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY){
					//Left for folders
					//Maybe I update this to scan sub folders to.
				}
				else{
					//Set input and output filenames
					SrcFile = sSrcFolder + wfd.cFileName;
					DestFile = sDestFolder + wfd.cFileName;

					//Copy files over to sDestFolder
					if (!MyFileCopy(SrcFile.c_str(), DestFile.c_str(), cpychunksize)){
						//Test for quite mode
						if (!Qmode){
							cout << wfd.cFileName << " ...Faild" << endl;
							//INC skipped files
							Skipped++;
						}
					}
					else{
						//Test for quite mode
						if (!Qmode){
							//Output ok copy message.
							cout << wfd.cFileName << " ...OK" << endl;
							//INC copied counter.
							Copied++;
						}
					}
					//
				}
			}

			//Close
			FindClose(f);
			//Test for quite mode
			if (!Qmode){
				//Output the number of copyied and skipped files.
				cout << endl;
				cout << "Files Coppied  : " << Copied << endl;
				cout << "Files Skipped  : " << Skipped << endl;
			}
		}
	}
	return EXIT_SUCCESS;
}